﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.Helpers;
using System.Web.Mvc;
using System.Web.Security;
using ImageHandler;
using MvcPaging;
using Stamp_For_Africa_Version_2.Helpers;
using Stamp_For_Africa_Version_2.Models;
using Stamp_For_Africa_Version_2.Repositories;
using Stamp_For_Africa_Version_2.ViewModels;

namespace Stamp_For_Africa_Version_2.Controllers
{
	
	public class StampsController : Controller
	{
		readonly StampRepository _stampRepository = new StampRepository();
		readonly StampFeatureRepository _stampFeatureRepository = new StampFeatureRepository();
		readonly ArtistRepository _artistRepository = new ArtistRepository();
		readonly ColourRepository _colourRepository = new ColourRepository();
		readonly CurrencyRepository _currencyRepository = new CurrencyRepository();
		readonly UploaderRepository _uploaderRepository = new UploaderRepository();
		readonly CountryRepository _countryRepository = new CountryRepository();
    readonly CategoryRepository _categoryRepository = new CategoryRepository();
		readonly CommentRepository _commentRepository = new CommentRepository();
    readonly CatalogueRepository _catalogueRepository = new CatalogueRepository();
    readonly TypeRepository _typeRepository = new TypeRepository();

		#region HTTP - GET Methods

    private Guid GetUserId()
    {
      MembershipUser user = Membership.GetUser();
      Guid userId = Guid.Empty;
      if (user != null)
        userId = (Guid)user.ProviderUserKey;

      return userId;
    }

		private void BuildViewBagItems()
		{
			List<SelectListItem> countryItems = _countryRepository.FindAllCountries().Select(c => new SelectListItem { Value = c.Id.ToString(), Text = c.Name }).ToList();
			List<SelectListItem> currencyItems = _currencyRepository.FindAllCurrencies().Select(c => new SelectListItem { Value = c.Id.ToString(), Text = c.DisplayName }).ToList();
			List<SelectListItem> artistItems = _artistRepository.FindAllArtists().Select(c => new SelectListItem { Value = c.Id.ToString(), Text = c.DisplayName }).ToList();
      List<SelectListItem> issueTypeList = _typeRepository.FindAllTypes().Select(c => new SelectListItem { Value = c.Id.ToString(), Text = c.DisplayName }).ToList();
		  List<SelectListItem> categoryItems =
		    _categoryRepository.FindAllCategories().Select(
		      c => new SelectListItem {Value = c.Id.ToString(), Text = c.DisplayName}).ToList();

			List<SelectListItem> issueType = new List<SelectListItem>();
			SelectListItem regularIssue = new SelectListItem
			                              	{
			                              		Text = "Regular (Definitive) Issue",
			                              		Value = "0"
			                              	};
			SelectListItem provisionalIssue = new SelectListItem
			                                  	{
			                                  		Text = "Provisional Issue",
			                                  		Value = "1"
			                                  	};
			SelectListItem commemorativeIssue = new SelectListItem
			                                    	{
			                                    		Text = "Commemorative Issue",
			                                    		Value = "2"
			                                    	};
			issueType.Add(regularIssue);
			issueType.Add(provisionalIssue);
			issueType.Add(commemorativeIssue);
			
			List<SelectListItem> firstIssueDates = new List<SelectListItem>();
			List<String> dates = _stampRepository.GetAllYears();
			foreach (var date in dates)
			{
				SelectListItem item = new SelectListItem
				                      	{
				                      		Text = date,
				                      		Value = date
				                      	};
				firstIssueDates.Add(item);
			}

			ViewBag.CountryList = countryItems;
			ViewBag.CurrencyList = currencyItems;
			ViewBag.ArtistList = artistItems;
		  ViewBag.CategoryList = categoryItems;
			ViewBag.IssueTypeList = issueType;
			ViewBag.FirstIssueList = firstIssueDates;
		  ViewBag.StampTypeList = issueTypeList;
		}

		//
		// GET: /Stamps/

		public ActionResult Index(int ?id)
		{
			StampIndexFormViewModel formViewModel = null;
			if (TempData.ContainsKey("FormFilters"))
			{
				var pageIndex = id ?? 0;
				formViewModel = (StampIndexFormViewModel)TempData["FormFilters"];
				formViewModel.StampPage = _stampRepository.SelectRange(pageIndex, 4, GetUserId());
				TempData["FormFilters"] = formViewModel;
				
			}
			else
			{
        var pageIndex = id ?? 0;
				formViewModel = new StampIndexFormViewModel();
				//formViewModel.StampList = _stampRepository.FindAllStamps().ToList();
			  //formViewModel.StampPage = _stampRepository.SelectRange(pageIndex, 4);
				
        formViewModel.PageNumber = 0;
			  formViewModel.PageCount = 0;
			  formViewModel.MaxResultsPerPage = 10;
			}

			BuildViewBagItems();

			return View("Index", formViewModel);
		}

		[AcceptVerbs(HttpVerbs.Post)]
		public ActionResult Index(int ?id, FormCollection formValues)
		{
			var formViewModel = new StampIndexFormViewModel();
			
			string selectedCountryId = formValues["SelectedCountryId"];
			string selectedCurrencyId = formValues["SelectedCurrencyId"];
			string selectedArtistId = formValues["SelectedArtistId"];
		  string selectedCategoryId = formValues["SelectedCategoryId"];
			string selectedIssueTypeId = formValues["SelectedIssueTypeId"];
			string selectedFirstYear = formValues["FirstIssue"];
			

			//formViewModel.StampList = _stampRepository.FindAllStamps(selectedCountryId, selectedArtistId, selectedCurrencyId, selectedCategoryId);
			var pageIndex = id ?? 0;
      formViewModel.StampPage = _stampRepository.SelectRange(pageIndex, 4, selectedCountryId, selectedCategoryId, selectedFirstYear, GetUserId(), selectedIssueTypeId, selectedArtistId);
			formViewModel.ContainsFilters = true;
			formViewModel.SelectedCountryId = selectedCountryId;
			formViewModel.SelectedArtistId = selectedArtistId;
			formViewModel.SelectedCurrencyId = selectedCurrencyId;
		  formViewModel.SelectedCategoryId = selectedCategoryId;
			formViewModel.SelectedIssueTypeId = selectedIssueTypeId;
			formViewModel.FirstIssue = selectedFirstYear;

			BuildViewBagItems();

			TempData.Clear();
			TempData.Add("FormFilters", formViewModel);

			return View("Index", formViewModel);
		}

		//
		// GET: /Stamp/Details/Id

		public ActionResult Details( Guid id )
		{

			Stamp stamp = _stampRepository.GetStamp(id, GetUserId());
			List<Comment> stampComments = _commentRepository.FindAllCommentsForStamp(stamp.Id).OrderByDescending(u => u.DateTime).ToList();
		  List<CatalogueEntry> catalogueEntries = _catalogueRepository.GetCatalogueEntriesForStamp(stamp.Id);
			StampDetailsViewModel stampDetailsViewModel = new StampDetailsViewModel();
			stampDetailsViewModel.Stamp = stamp;
			stampDetailsViewModel.StampComments = stampComments;
		  stampDetailsViewModel.CatalogueEntries = catalogueEntries;
			if (stamp == null)
				return View("NotFound");
			else
				return View("Details", stampDetailsViewModel);
		}


		//
		// GET: /Stamps/Create
		[Authorize]
		public ActionResult Create()
		{

			Stamp stamp = new Stamp()
			              	{
			              		ArtistId = _artistRepository.GetArtist(new Guid("00000000-0000-0000-0000-000000000000")).Id,
			              		PrimaryColorId = _colourRepository.GetColour(new Guid("00000000-0000-0000-0000-000000000000")).Id,
			              		CurrencyId = _currencyRepository.GetCurrency(new Guid("00000000-0000-0000-0000-000000000000")).Id,
			              		UploaderId = _uploaderRepository.GetUploader(new Guid("00000000-0000-0000-0000-000000000000")).Id,
			              		CountryId = _countryRepository.GetCountry(new Guid("00000000-0000-0000-0000-000000000000")).Id,
												
                        NonRootedUploadedFileName = "/Images/SelectStamp.jpg"
											};

			ViewData["userCountryId"] = new SelectList(_countryRepository.FindAllCountries().ToList(), "Id", "Name", stamp.CountryId);
			ViewData["userArtistId"] = new SelectList(_artistRepository.FindAllArtists().ToList(), "Id", "Name", stamp.ArtistId );
			ViewData["userColourId"] = new SelectList(_colourRepository.FindAllColours().ToList(), "Id", "Colour1",
			                                          stamp.PrimaryColorId);
			ViewData["userUploaderId"] = new SelectList(_uploaderRepository.FindAllUploaders().ToList(), "Id", "Name", stamp.UploaderId);
			ViewData["userCurrencyId"] = new SelectList(_currencyRepository.FindAllCurrencies().ToList(), "Id", "DisplayName", stamp.CurrencyId);
		  ViewData["userCategoryId"] = new SelectList(_categoryRepository.FindAllCategories().ToList(), "Id", "DisplayName",
		                                              stamp.CategoryId);

			return View(stamp);
		}

		//
		// GET: /Stamps/Edit/2
		[Authorize]
		public ActionResult Edit(Guid id)
		{

			Stamp stamp = _stampRepository.GetStamp(id, Guid.Empty);

			return View(stamp);
		}


		//
		// GET: /Artists/Delete/xxx
		[Authorize]
		public ActionResult Delete(Guid id)
		{

			Stamp stamp = _stampRepository.GetStamp(id, Guid.Empty);

			if (stamp == null)
				return View("NotFound");
			else
				return View(stamp);
		}

		#endregion

		#region HTTP - POST Methods

		//
		// POST: /Artists/Create
		[Authorize]
		[AcceptVerbs(HttpVerbs.Post)]
		public ActionResult Create(Stamp stamp)
		{
			if (ModelState.IsValid)
			{

				try
				{
					stamp.Id = Guid.NewGuid();

					ImageMatch imageMatch = new ImageMatch();
					imageMatch.LoadGivenImageFromImageFile(stamp.UploadedFileName);

					//Save temp image features
					String featureFile = stamp.UploadedFileName + ".bin";
					FileImagePersistence.SaveImageFeatures(stamp.UploadedFileName, featureFile);
					Byte[] fileBytes = FileImagePersistence.ReadFileBytes(stamp.UploadedFileName);
					Byte[] featureBytes = FileImagePersistence.ReadFileBytes(featureFile);
					FileImagePersistence.DeleteFile(featureFile);


					stamp.Image = fileBytes;

					StampFeature feature = new StampFeature();
					feature.Id = Guid.NewGuid();
					feature.Features = featureBytes;
					_stampFeatureRepository.Add(feature);
					_stampFeatureRepository.Save();

					stamp.FeatureId = feature.Id;

					_stampRepository.Add(stamp);
					_stampRepository.Save();


					return RedirectToAction("Details", new { id = stamp.Id });
				}
				catch
				{
					ModelState.AddRuleViolations(stamp.GetRuleViolations());
				}
			}

			return View(stamp);
		}

		//
		// POST: /Artists/Edit/xxx
		[Authorize]
		[AcceptVerbs(HttpVerbs.Post)]
		public ActionResult Edit(Guid id, FormCollection formValues)
		{
			Stamp stamp = _stampRepository.GetStamp(id, Guid.Empty);

			try
			{

				UpdateModel(stamp);
				_stampRepository.Save();

				return RedirectToAction("Details", new { id = stamp.Id });
			}
			catch
			{
				ModelState.AddRuleViolations(stamp.GetRuleViolations());

				return View(stamp);
			}


		}

		//
		// HTTP POST: /Artists/Delete/xxx
		[Authorize]
		[AcceptVerbs(HttpVerbs.Post)]
		public ActionResult Delete(Guid id, string confirmButton)
		{

			Stamp stamp = _stampRepository.GetStamp(id, Guid.Empty);

			if (stamp == null)
				return View("NotFound");

			_stampRepository.Delete(stamp);
			_stampRepository.Save();

			return View("Deleted");
		}

		#endregion

	
	

		public ActionResult SearchStamps()
		{

			StampIndexFormViewModel formViewModel = null;
			if (TempData.ContainsKey("FormFilters"))
			{
				formViewModel = (StampIndexFormViewModel)TempData["FormFilters"];
				TempData["FormFilters"] = formViewModel;
			}
			else
			{
				formViewModel = new StampIndexFormViewModel();
				//formViewModel.StampList = _stampRepository.FindAllStamps(GetUserId()).ToList();				
			}

			BuildViewBagItems();
			if (formViewModel.NonRootedFileForSearch == null)
				formViewModel.NonRootedFileForSearch = "/Images/SelectStamp.jpg";
			return View("SearchStamps", formViewModel);
		}

		[Authorize]
		[AcceptVerbs(HttpVerbs.Post)]
		public ActionResult FileUpload(StampImageUploadModel uploadedFileMeta)
		{
			
			try
			{
				var fileName = this.Server.MapPath("~/uploads/" + System.IO.Path.GetFileName( uploadedFileMeta.fileData.FileName));
				var nonRootedPath = "/uploads/" + System.IO.Path.GetFileName(uploadedFileMeta.fileData.FileName);
				uploadedFileMeta.fileData.SaveAs(fileName);
				return Json(new { Status = "OK", returnFile = fileName, serverPath = nonRootedPath });
			}
			catch (Exception ex)
			{
				return Json(new { Status = "Failed" });
			}

		}
		
		[AcceptVerbs(HttpVerbs.Get)]		
		public ActionResult ShowStamp(Guid id)
		{
			StampRepository repository = new StampRepository();

			Stamp stamp = repository.GetStamp(id, GetUserId());
			if (stamp != null)
				return File(stamp.Image.ToArray(), "image/jpg");
			else
			{
				return null;
			}
		}

		[AcceptVerbs(HttpVerbs.Get)]
		public ActionResult ShowControlBlock(Guid id)
		{
			StampRepository repository = new StampRepository();

			Stamp stamp = repository.GetStamp(id, GetUserId());
			if (stamp != null)
			{
				if (stamp.ControlBlockImage == null)
					return null;
				return File(stamp.ControlBlockImage.ToArray(), "image/jpg");
			}
			else
			{
				return null;
			}
		}

		

		[Authorize]
		[AcceptVerbs(HttpVerbs.Post)]
		public ActionResult PostCommentToStamp(String stampId, String scomment)
		{
			if (String.IsNullOrEmpty(stampId) || String.IsNullOrEmpty(scomment))
			{
				return Json(new { Status = "Failed" });
			}

			Guid sGuid = Guid.Parse(stampId);


			Comment comment = new Comment();
			comment.Comment1 = scomment;
			comment.CommentBy = GetUserId();
			comment.CommentIndex = 0;
			comment.DateTime = DateTime.Now;
			comment.Id = Guid.NewGuid();
			comment.StampId = sGuid;
			comment.CommentDisplayName = User.Identity.Name;
			
			CommentRepository commentRepository = new CommentRepository();
			commentRepository.Add(comment);
			commentRepository.Save();

			return Json(new { Status = "Ok" });
		}


		public ActionResult DoSearch(FormCollection formCollection)
		{
			String imagePath = formCollection["UserUploadedFileForSearch"];
			String sMaxResults = formCollection["MaxResults"];
			String serverPath = formCollection["NonRootedFileForSearch"];
			String SearchCategoryId = formCollection["SearchCategoryId"];
			String SearchCountryId = formCollection["SearchCountryId"];
			String SearchCurrencyId = formCollection["SearchCurrencyId"];
			String SearchText = formCollection["SearchText"];


			if (!String.IsNullOrEmpty(imagePath))
			{
				return DoImageSearch(imagePath, sMaxResults, serverPath, SearchCategoryId, SearchCountryId, SearchText);
			}
			else
			{
				return TextSearch(sMaxResults, SearchCategoryId, SearchCountryId, SearchText);
			}



			
		}


		public ActionResult TextSearch(String sMaxResults, String SearchCategoryId, String SearchCountryId, String SearchText)
		{

			if (String.IsNullOrEmpty(SearchText))
				return RedirectToAction("SearchStamps");

			TextSearcher searcher = new TextSearcher();
 			searcher.BuildTextSearcher(SearchText);
			searcher.RunTextSearch();

			if (String.IsNullOrEmpty(sMaxResults))
				sMaxResults = "10";

			SearchFormViewModel searchFormViewModel = new SearchFormViewModel();
			searchFormViewModel.SearchResults = searcher.HitList.Select(u => u.Stamp);
			searchFormViewModel.SearchedWithImage = false;
			return View("SearchResults", searchFormViewModel); 


			//List<Stamp> countries = _stampRepository.FindAllStamps()

			/*
			Guid countryGuid = Guid.Empty;
			Guid categoryGuid = Guid.Empty;
			if (!String.IsNullOrEmpty(SearchCountryId))
				countryGuid = Guid.Parse(SearchCountryId);
			if (!String.IsNullOrEmpty(SearchCategoryId))
				categoryGuid = Guid.Parse(SearchCategoryId);

			IQueryable<Stamp> results = _stampRepository.FindAllStamps(Guid.Empty);
			if (countryGuid != Guid.Empty)
			{
				results = results.Where(u => u.CountryId == countryGuid);
			}
			if (categoryGuid != Guid.Empty)
			{
				results = results.Where(u => u.CategoryId == categoryGuid);
			}

			//Text search
			*/
			/*
			StampIndexFormViewModel formViewModel = null;
			if (TempData.ContainsKey("FormFilters"))
			{
				formViewModel = (StampIndexFormViewModel)TempData["FormFilters"];
				TempData["FormFilters"] = formViewModel;
			}
			else
			{
				formViewModel = new StampIndexFormViewModel();
				formViewModel.StampList = _stampRepository.SearchRange(0, 4, SearchText, "", "", "", GetUserId());
			}

			BuildViewBagItems();
			*/
			

		}

    public ActionResult DoImageSearch(String imagePath, String sMaxResults, String serverPath, String SearchCategoryId, String SearchCountryId, 
			String SearchText)
    {

      if (String.IsNullOrEmpty(sMaxResults))
        sMaxResults = "10";

      MatchResults matchResults = new MatchResults();
      //matchResults.MaxResults = 10;

      if (!String.IsNullOrEmpty(imagePath))
      {
        matchResults = Helpers.ImageSearcher.FindBestImagesMatches(imagePath, int.Parse(sMaxResults));
        if (TempData["SearchResults"] != null)
          TempData.Remove("SearchResults");
        TempData.Add("SearchResults", matchResults);
        if (TempData["SearchedImage"] != null)
          TempData.Remove("SearchedImage");
        if (TempData["UserServerImagePath"] != null)
          TempData.Remove("UserServerImagePath");

        TempData.Add("SearchedImage", imagePath);
        TempData.Add("UserServerImagePath", serverPath);
      }
      return RedirectToAction("SearchResults", "Stamps");
    }

    public ActionResult SearchResults()
    {
      MatchResults matchResults = null;
      StampRepository repository = new StampRepository();
      String searchedImage = "";
      String searchedImageServerPath = "";
      if (TempData["SearchResults"] != null)
      {
        matchResults = (MatchResults)TempData["SearchResults"];
      }
      if (TempData["SearchedImage"] != null)
      {
        searchedImage = (string)TempData["SearchedImage"];
      }
      if (TempData["UserServerImagePath"] != null)
        searchedImageServerPath = (string) TempData["UserServerImagePath"];

			SearchFormViewModel searchFormViewModel = new SearchFormViewModel();
			searchFormViewModel.SearchResults = repository.FindAllStamps(matchResults);
    	searchFormViewModel.SearchedWithImage = true;
      searchFormViewModel.ImageSearchedFor = searchedImage;
      searchFormViewModel.NonRootedImageSearchedFor = searchedImageServerPath; 
      return View(searchFormViewModel); 

      
    }




		#region Quick add Posts
		// ================================================================
		//	The actions in this region allow you to quickly add a new
		//	country, artist, category, currency or colour by making
		//  use of a dialog
		// ================================================================
    [Authorize]
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult AddStampToCollection(String stampId, String MintNH, String MintH, String Used)
    {
      CollectionRepository collectionRepository = new CollectionRepository();

			collectionRepository.AddStampToCollection(GetUserId(), Guid.Parse(stampId), MintNH, MintH, Used);

      return Json(new { Result = "Failed" });      
    }

		[Authorize]
		[AcceptVerbs(HttpVerbs.Post)]
		public ActionResult RemoveStampsFromCollection(String stampId, String MintNH, String MintH, String Used)
		{
			CollectionRepository collectionRepository = new CollectionRepository();

			collectionRepository.RemoveStampsFromCollection(GetUserId(), Guid.Parse(stampId), MintNH, MintH, Used);

			return Json(new { Result = "Failed" });
		}


		[Authorize]
		[AcceptVerbs(HttpVerbs.Post)]
		public ActionResult DeleteStampsFromCollection(String stampId)
		{
			CollectionRepository collectionRepository = new CollectionRepository();

			collectionRepository.RemoveAllCollectionsWithStampId(GetUserId(), Guid.Parse(stampId));

			return Json(new { Result = "Failed" });
		}


		

		[Authorize]
		[AcceptVerbs(HttpVerbs.Post)]
		public ActionResult CreateCountry(String countryName)
		{
			if (!String.IsNullOrEmpty(countryName))
			{
				CountryRepository repository = new CountryRepository();
				if (repository.FindAllCountries(countryName).Count() == 1)
				{
					return Json(new { Result = "Country already exists" });
				}

				Country country = new Country();
				country.Id = Guid.NewGuid();
				country.Name = countryName;
				repository.Add(country);
				repository.Save();
				return Json(new { Result = "Success", CountryName = countryName, CountryId = country.Id });
			}

			return Json(new { Result = "Failed" });

		}

		[Authorize]
		[AcceptVerbs(HttpVerbs.Post)]
		public ActionResult CreateArtist(String name, String surname)
		{
			if (!String.IsNullOrEmpty(name) && !String.IsNullOrEmpty(surname))
			{
				ArtistRepository repository = new ArtistRepository();
				if (repository.FindAllArtists(name, surname).Count() == 1)
				{
					return Json(new { Result = "Artist already exists" });
				}

				Artist artist = new Artist();
				artist.Id = Guid.NewGuid();
				artist.Name = name;
				artist.Surname = surname;
				repository.Add(artist);
				repository.Save();
				return Json(new { Result = "Success", artistName = artist.DisplayName, artistId = artist.Id });
			}

			return Json(new { Result = "Failed" });

		}

		[Authorize]
		[AcceptVerbs(HttpVerbs.Post)]
		public ActionResult CreateCurrency(String displayName, String symbol)
		{
			if (!String.IsNullOrEmpty(displayName) && !String.IsNullOrEmpty(symbol))
			{
				CurrencyRepository repository = new CurrencyRepository();
				if (repository.FindAllCurrencies().Where(u => u.CurrencyText.ToLower() == symbol).Count() == 1)
				{
					return Json(new { Result = "Currency already exists" });
				}

				Currency currency = new Currency();
				currency.Id = Guid.NewGuid();
				currency.DisplayName = displayName;
				currency.CurrencyText = symbol;
				repository.Add(currency);
				repository.Save();
				return Json(new { Result = "Success", currencyName = currency.DisplayName, currencyId = currency.Id });
			}

			return Json(new { Result = "Failed" });

		}

		[Authorize]
		[AcceptVerbs(HttpVerbs.Post)]
		public ActionResult CreateColour(String colourName)
		{
			if (!String.IsNullOrEmpty(colourName))
			{
				ColourRepository repository = new ColourRepository();
				if (repository.FindAllColours().Where(u => u.Colour1.ToLower() == colourName.ToLower()).Count() == 1)
				{
					return Json(new { Result = "Colour already exists" });
				}

				Colour colour = new Colour();
				colour.Id = Guid.NewGuid();
				colour.Colour1 = colourName;
				repository.Add(colour);
				repository.Save();
				return Json(new { Result = "Success" });
			}

			return Json(new { Result = "Failed" });

		}

		[Authorize]
		[AcceptVerbs(HttpVerbs.Post)]
		public ActionResult CreateCategory(String categoryName)
		{
			if (!String.IsNullOrEmpty(categoryName))
			{
				CategoryRepository repository = new CategoryRepository();
				if (repository.FindAllCategories().Where(u => u.DisplayName.ToLower() == categoryName.ToLower()).Count() == 1)
				{
					return Json(new { Result = "Category already exists" });
				}

				Category category = new Category();
				category.Id = Guid.NewGuid();
				category.DisplayName = categoryName;
				repository.Add(category);
				repository.Save();
				return Json(new { Result = "Success", CategoryName = category.DisplayName, CategoryId = category.Id });
			}

			return Json(new { Result = "Failed" });

		}


		#endregion

	}

			
}
